package com.coda.app.service.impl;

import com.coda.app.mapper.LoginMapper;
import com.coda.app.service.LoginService;
import com.coda.app.service.SmsService;
import com.coda.appVo.user.LoginVo;
import com.coda.appVo.user.UserInfoVo;
import com.coda.constant.MessageConstant;
import com.coda.constant.RedisConstant;
import com.coda.constant.StatusConstant;
import com.coda.context.BaseContext;
import com.coda.entity.UserInfo;
import com.coda.exception.BaseException;
import com.coda.exception.StatusIsStartException;
import com.coda.exception.TTLException;
import com.coda.properties.JwtAppProperties;
import com.coda.utils.CodeUtils;
import com.coda.utils.JwtUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private SmsService smsService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private LoginMapper loginMapper;
    @Autowired
    private JwtAppProperties jwtAppProperties;

    /**
     * 发送验证码
     *
     * @param phone
     */
    @Override
    public void getCode(String phone) {

        //生成验证码,作为redis value
        String Code = CodeUtils.getRandomCode(6);
        //手机号码 redis key
        String key = RedisConstant.APP_LOGIN_PREFIX + phone;

        //1分钟之内不能重复发短信
        //判断key是否存在
        if (redisTemplate.hasKey(key)) {
            //获取key的当前剩余时间
            Long ttl = redisTemplate.getExpire(key);
            //如果时间<60ms 不能重复发短信
            if (RedisConstant.APP_LOGIN_CODE_TTL_SEC - ttl < 60) {
                throw new TTLException(MessageConstant.REPEAT_SEND);
            }
        }
        smsService.sendCode(phone, Code);
        redisTemplate.opsForValue().set(key, Code, RedisConstant.APP_LOGIN_CODE_TTL_SEC, TimeUnit.SECONDS);
    }

    /**
     * 登录或注册
     *
     * @param loginVo
     * @return
     */
    @Override
    public String login(LoginVo loginVo) {
        String phone = loginVo.getPhone();
        String code = loginVo.getCode();
        //判断手机号或验证码是否为空
        if (phone == null) {
            throw new BaseException(MessageConstant.PHONE_NULL);
        }
        if (code == null) {
            throw new BaseException(MessageConstant.CODE_NULL);
        }

        //判断验证码是否过期
        String key = RedisConstant.APP_LOGIN_PREFIX + phone;
        if (!(redisTemplate.hasKey(key))) {
            throw new BaseException(MessageConstant.CODE_OVERDUE);
        }

        //判断验证码是否正确
        if (!(redisTemplate.opsForValue().get(key).equals(code))) {
            throw new BaseException(MessageConstant.CODE_ERR);
        }

        //查询数据库，如果为空则新建用户
        UserInfo userInfo = loginMapper.getUserByPhone(phone);
        if (userInfo == null) {
            userInfo = new UserInfo();
            userInfo.setPhone(phone);
            userInfo.setStatus(StatusConstant.ENABLE);
            userInfo.setPassword(DigestUtils.md5Hex("123456".getBytes()));
            userInfo.setNickname("用户-" + phone.substring(phone.length() - 4));
            loginMapper.insert(userInfo);
        }

        //判断用户是否被禁用
        if (userInfo.getStatus() == 0) {
            throw new StatusIsStartException(MessageConstant.USER_STATUS_STOP);
        }

        //创建jwt令牌
        HashMap<String, Object> claims = new HashMap<>();
        claims.put("appId", userInfo.getId());
        String token = JwtUtil.createJWT(
                jwtAppProperties.getUserSecretKey(),
                jwtAppProperties.getUserTtl(),
                claims);
        return token;
    }

    /**
     * 获取登录用户信息
     * @return
     */
    @Override
    public UserInfoVo getUserInfo() {
        UserInfo userInfo = loginMapper.getUserInfo(BaseContext.getCurrentId());
        UserInfoVo userInfoVo = new UserInfoVo(userInfo.getNickname(),userInfo.getAvatarUrl());
        return userInfoVo;
    }
}
